# 导入SQLAlchemy的create_engine、Column、Integer、String、ForeignKey等组件
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey

# 导入relationship用于定义表间关系，declarative_base用于创建ORM基类
from sqlalchemy.orm import relationship, declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from en_url import engine

# 创建MySQL数据库连接引擎，指定数据库连接字符串
# 创建声明性基类，所有ORM模型类都将继承自该基类
Base = declarative_base()


# 定义User模型类，继承自Base
class User(Base):
    # 指定该模型对应的表名为'users'
    __tablename__ = "users"

    # 定义id字段，类型为整型，主键
    id = Column(Integer, primary_key=True)
    # 定义name字段，类型为字符串
    name = Column(String)
    # 定义fullname字段，类型为字符串
    fullname = Column(String)
    # 定义与Address表的一对多关系，back_populates用于反向引用
    addresses = relationship("Address", back_populates="user")

    # 使用hybrid_property装饰器定义混合属性，该属性既可以在Python对象上使用，也可以在SQL查询中使用
    @hybrid_property
    # 定义description方法，用于生成用户的描述信息
    def description(self):
        # 使用列表推导式获取用户所有地址的邮箱地址，并用逗号连接成字符串
        email_addresses = ", ".join([addr.email_address for addr in self.addresses])
        # 返回包含用户全名和邮箱地址的描述字符串
        return f"{self.fullname} {email_addresses}"


# 定义Address模型类，继承自Base
class Address(Base):
    # 指定该模型对应的表名为'addresses'
    __tablename__ = "addresses"

    # 定义id字段，类型为整型，主键
    id = Column(Integer, primary_key=True)
    # 定义email_address字段，类型为字符串，不能为空
    email_address = Column(String, nullable=False)
    # 定义user_id字段，类型为整型，外键关联users表的id字段
    user_id = Column(Integer, ForeignKey("users.id"))
    # 定义与User表的多对一关系，back_populates用于反向引用
    user = relationship("User", back_populates="addresses")


# 在数据库中创建所有已定义的表
Base.metadata.create_all(engine)

# 导入sessionmaker用于创建数据库会话
from sqlalchemy.orm import sessionmaker

# 创建会话工厂，并绑定到数据库引擎
Session = sessionmaker(bind=engine)
# 创建数据库会话对象，用于与数据库进行交互
session = Session()
# 定义要批量插入User表的数据，每个字典代表一条用户记录
# 批量插入
# users_data = [
#     {"name": "alice", "fullname": "Alice Wonderland"},
#     {"name": "bob", "fullname": "Bob Builder"},
#     {"name": "cathy", "fullname": "Cathy Smith"},
# ]
# # # 使用bulk_insert_mappings批量插入方法将users_data批量插入到User表中
# session.bulk_insert_mappings(User, users_data)
# # 提交事务，将插入操作保存到数据库
# session.commit()
# # 查询User表中的所有用户，并打印每个用户的姓名和用户名
# for user in session.query(User).all():
#     print(f"id: {user.id} 姓名: {user.fullname}，用户名: {user.name}")

# 定义要批量更新User表的数据，每个字典包含要更新的主键id和新字段值
# update_data = [
#     {"id": 18, "fullname": "雷超大帅哥", "name": "雷神"},
#     {"id": 19, "fullname": "雷超大帅哥222", "name": "雷军"},
# ]
# # 使用bulk_update_mappings方法批量更新User表
# session.bulk_update_mappings(User, update_data)
# # 提交事务，将更新操作保存到数据库
# session.commit()

# # 再次查询User表，打印更新后的用户信息
print("批量更新后：")
for user in session.query(User).all():
    print(f"description: {user.description}")
